package com.AdvancedDemos.FileAndIO;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Learn字节流 {
    public static void main(String[] args) throws IOException {
        /**
         * IO概述:
         * IO是数据 读写 操作
         * IO是站在内存角度来看数据的,程序运行在内存,运行过程中需要数据支持或者产生数据
         * I:站在内存角度,将数据读取到内存 -- 内存(往里)读 Input
         * O:站在内存角度,将内存中数据写出 -- 内存(往外)写 Output
         *
         * IO分类:
         * 1.操作字节数据(字节流):可以适用于任何类型文件,主要适用于文件传输,拷贝文件CV
         * 2.操作字符数据(字符流):只适用于纯文本文件(没有任何文本样式,只有文字)
         */

        //字节输入流FileInputStream:
        //流向:从硬盘读取到内存
        //1.构造
        //参数可以传递:
        // 1.String path:字符串表示形式路径(推荐)
        // 2.File file:File对象
        FileInputStream fileInputStream = new FileInputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\a.txt");
        System.out.println(fileInputStream.toString());//java.io.FileInputStream@10f87f48

        //2.单字节读取操作 int read() 方法返回字符对应的字节数据值(ASCII码) 读取完毕后游标自动往后一个字节
        int read = fileInputStream.read();
        System.out.println(read);//77
        System.out.println((char) read);//M


        //循环中使用read()方法读取文件所有内容
        while ((read = fileInputStream.read()) != -1) {//文件结束标记是整数值-1
            System.out.print((char) read);//y name is ABC.
        }
        System.out.println();


        //3.读取完毕,关闭流,释放资源,解除文件占用状态(读取到文件末尾不意味着释放资源,必须执行close()或者虚拟机停止)
        fileInputStream.close();

        //4.字节数组读取
        fileInputStream = new FileInputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\a.txt");
        byte[] bytes = new byte[7];//每次读7个字节
        int count;
        while ((count = fileInputStream.read(bytes)) != -1) {
            //返回值是读取字节的个数,没有到末尾时,读取几个字节就返回几;
            //到末尾了一个字节都没读到返回-1;
            //传递的数组是复用的,新读取的数据会覆盖旧的数据,会导致残留数据产生(从前往后覆盖)
            System.out.println("本次读取到" + count + "个字节");
            System.out.println(new String(bytes, 0, count));//将字节数组使用String构造函数转换为字符串
            // 参数1:要转换的字节数组
            // 参数2:其实转换索引
            // 参数3:表示有效读取字节个数 ,  通过指定为read(bytes)的返回值,即count实际读取的字节数,来避免打印出上次读取中bytes中残留的未被覆盖的部分
            // 即如果直接new String(bytes)
            //结果将是
            /*
            本次读取到7个字节
            My name
            本次读取到7个字节
             is ABC
            本次读取到1个字节
            .is ABC
             */
            //本次读取到7个字节
            //My name
            //本次读取到7个字节
            // is ABC
            //本次读取到1个字节
            //.
        }
        fileInputStream.close();


        //5.读取文件全部字节
        File path = new File("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\a.txt");
        if (path.length() >= Integer.MAX_VALUE) {//防止文件过大
            throw new RuntimeException("文件过大!");
        }//防一手
        fileInputStream = new FileInputStream(path);
        byte[] bytes1 = fileInputStream.readAllBytes();//读取全部字节,放到字节数组中   注意:最大读取容量是Integer.MAX_VALUE
        System.out.println("数组长度是:" + bytes1.length);
        System.out.println(new String(bytes1));
        //数组长度是:15
        //My name is ABC.
        fileInputStream.close();


        //6.字节输出流对象获取
        //构造方法
        //参数:
        //1.String路径
        //2.File对象
        //3.boolean类型的append追加写入开关

        //使用构造方法关联路径:
        FileOutputStream fileOutputStream = new FileOutputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\gbk.txt", true);//如果不指定为true(打开追加),默认为false(关闭追加,直接覆盖原文件)
        //1.如果表示的文件不存在,将会创建文件,但是文件父级路径必须存在
        //否则报错FileNotFoundException系统找不到指定路径
        //2.如果表示的文件已经存在,在不开启追加写入开关的情况下,会清空原来文件的内容
        //3.如果表示的文件已经存在,开启了追加写入开关,将会保留原来文件内容,输出的内容在后面追加


        //7.单字节写出操作
        //参数传递int数据值,实际是字符值 'A'--65 'a'--97
        //为了传递数据方便,可以利用自动类型转换 int c = 'a';
        fileOutputStream.write('a');//开启追加会直接在原文件内容后面追加,关闭追加会先清空原文件内容再写入


        //8.字节输出流写出字节数组
        byte[] bytes2 = new byte[]{'a', 'b', 'c'};
        String s = "WangTianpei";
        byte[] bytes3 = s.getBytes();
        fileOutputStream.write(bytes2);//输出字节数组
        fileOutputStream.write("\r\n".getBytes());//输出换行符,windows下换行是\r\n
        fileOutputStream.write(bytes3);
        System.out.println(' ');
        fileOutputStream.write(bytes3, 0, 4);//从指定偏移开始输出指定长度的字节数组
        fileOutputStream.write("\r\n".getBytes());


        fileOutputStream.close();
    }
}
